package com.flowcanto.gs1demo.server;

/**
 * Handles the receiving of an order. 
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

import net.sf.saxon.Controller;
import net.sf.saxon.StandardURIResolver;
import net.sf.saxon.Transform;
import net.sf.saxon.TransformerFactoryImpl;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;

public class OrderHandler extends javax.servlet.http.HttpServlet {
	Webserver server;
	String orderID;
	File orderFile;
	// Start the thread in the constructor
	public OrderHandler(Webserver server) {
		this.server = server;
	}
	
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
		throws ServletException, java.io.IOException {
		doPut(req, resp);
	}

	protected void doPut(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, java.io.IOException {
		System.out.println("do put");		
		StringWriter body = new StringWriter(req.getContentLength());
		BufferedReader in = req.getReader();
		while (in.ready())
			body.write(in.readLine()+'\n');
		//System.out.print(body.toString());
		handleOrder(body.toString());
	}

	public void handleOrder(String strOrder) throws ServletException {
		saveOrder(strOrder);
		String invoice = transform("xslt/OrderToInvoice.xsl", "output/orders/order_"+orderID+".xml");
		try {
			saveFile(new File(server.applicationDirectory(), "output/invoice_"+orderID+".xml"), invoice);
		} catch (Exception e) {
			throw new ServletException(e);
		}	
		String despatchAdvice = transform("xslt/OrderToDespatchAdvice.xsl", "output/orders/order_"+orderID+".xml");
		try {
			saveFile(new File(server.applicationDirectory(), "output/despatchadvice_"+orderID+".xml"), despatchAdvice);
		} catch (Exception e) {
			throw new ServletException(e);
		}	
		System.out.println("handled order: " + orderFile.getPath());

  }	


	public void saveFile(File f, String contents) throws SecurityException, IOException{
		PrintWriter sfile = null;
		try {
			sfile = new PrintWriter(f);
			sfile.print(contents);
		} finally {
			if (sfile != null)
				sfile.close();
		}
	}

	public String transform(String xslFile, String xmlFile) {
		final StringWriter res = new StringWriter();
		try {
			System.out.println(server.applicationDirectory());
			StandardURIResolver urir = new StandardURIResolver(new net.sf.saxon.Configuration());
			TransformerFactoryImpl tfi = new TransformerFactoryImpl();
			Source fxsl = (Source) urir.resolve(xslFile, server.applicationDirectory());
			Controller xsl = (Controller) tfi.newTransformer(fxsl);
			Source xsd = (Source) Transform.loadDocuments(
				server.applicationDirectory() +  xmlFile, false, null, false);
			javax.xml.transform.stream.StreamResult resr = new javax.xml.transform.stream.StreamResult(res);
			xsl.transform(xsd, resr);
			System.out.println("result: "+resr.toString());

		} catch (TransformerException e) {
			System.out.println(e.getCause() );
			throw new Error(e);	
		}

		return res.toString();
	}

	/**
	* Saves the incomming file to output/order_<orderID>.xml
	* sets orderID and orderFile */
  private void saveOrder(String strOrder) throws ServletException {
		try {
			File tmpOrderFile = File.createTempFile("tmporder", ".xml");
			saveFile(tmpOrderFile, strOrder);
			
			DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
			Document docOrder = db.parse(tmpOrderFile);
			NamedNodeMap atts = docOrder.getFirstChild().getAttributes();
			XPath xp = XPathFactory.newInstance().newXPath();
			NamespaceContext namespaceContext=new NamespaceContextImpl(atts);
			xp.setNamespaceContext(namespaceContext);
			orderID = xp.evaluate("/FoodservicePurchaseOrder/Identifier", docOrder);
			System.out.println(orderID+" - " );
			orderFile = new File(server.applicationDirectory() 
				+ "output/orders/order_"+orderID+".xml" );

			if (orderFile.exists())
				throw new ServletException("Ordernummer ("+orderID+") bestaat al in het systeem. " + orderFile);
			else {
				saveFile( orderFile, strOrder );
			}	
		} catch (ServletException e) {
			throw e;
		}	catch (Exception e) {
			System.out.println(e);
			e.printStackTrace();
			throw new ServletException(e);
		}	
		
	}


}
